package com.platform.core.web.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.util.IdUtil;
import com.google.code.kaptcha.Producer;
import com.google.common.util.concurrent.RateLimiter;
import com.platform.comm.config.properties.JwtProperties;
import com.platform.core.service.LoginService;
import com.platform.comm.web.results.DataJsonResult;
import com.platform.comm.web.results.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY;
import static com.google.common.util.concurrent.RateLimiter.create;
import static com.platform.kaptcha.handler.CaptchaHandler.VALIDATE_CODE_PREFIX;

/**
 * @author coder
 */
@SuppressWarnings("UnstableApiUsage")
@Slf4j
@RestController
public class LoginController {

    private final LoginService loginService;
    private final JwtProperties jwtProperties;
    private final Producer captchaBean;
    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 每秒只发出100个令牌
     */
    private RateLimiter rateLimiter;

    @Autowired
    public LoginController(LoginService loginService, JwtProperties jwtProperties, Producer captchaBean,
                           RedisTemplate<String, Object> redisTemplate) {
        this.loginService = loginService;
        this.jwtProperties = jwtProperties;
        this.captchaBean = captchaBean;
        this.rateLimiter = create(100.0);
        this.redisTemplate = redisTemplate;
    }

    @PostMapping("/login_error")
    public JsonResult loginError(){
        JsonResult result = JsonResult.of();
        result.fail("登录失败");
        return result;
    }
    @PostMapping("/login_success")
    public JsonResult loginSuccess(){
        JsonResult response = JsonResult.of();
        response.apply("1", "登录成功");
        return response;
    }

    @PostMapping("/login_page")
    public JsonResult root(){
        JsonResult response = JsonResult.of();
        response.fail("尚未登录，请登录");
        return response;
    }

    @PostMapping(name = "获取验证码", path = "/auth/verifyCode")
    public Map<String, String> handle() {
        // 生成验证码
        String capText = captchaBean.createText();
        String capStr = capText.substring(0, capText.lastIndexOf("@"));
        String code = capText.substring(capText.lastIndexOf("@") + 1);
        BufferedImage image = captchaBean.createImage(capStr);
        // 缓存验证码至Redis
        String uuid = IdUtil.simpleUUID();
        redisTemplate.opsForValue().set(VALIDATE_CODE_PREFIX + uuid, code, 60*60, TimeUnit.SECONDS);
        // 转换流信息写出
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", os);
        } catch (IOException e) {
            return null;
        }

        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("code","00");
        resultMap.put("uuid", uuid);
        resultMap.put("img", Base64.encode(os.toByteArray()));

        return resultMap;
    }

    @PostMapping("/auth/login")
    public DataJsonResult<String> getToken(@RequestBody Map<String, String> paramsMap ){
        return DataJsonResult.succeed(loginService.login(paramsMap.get("username"), paramsMap.get("password")));
    }

    @PostMapping(value = "/auth/logout")
    public JsonResult wlogout(HttpServletRequest request){
        String token = request.getHeader(jwtProperties.getHeader());
        JsonResult result = JsonResult.of();
        if (token == null) {
            return result.fail("未提供token");
        }
        loginService.logout(token);
        return result.succeed();
    }

    @PostMapping("/auth/refreshToken")
    public DataJsonResult<String> refreshToken(@RequestBody Map<String, String> paramsMap){
        return DataJsonResult.succeed(loginService.refreshToken(paramsMap.get("token")));
    }

    @PostMapping("/auth/getTokenByName")
    public DataJsonResult<String> getTokenByName(@RequestBody Map<String, String> paramsMap){
        return DataJsonResult.succeed(loginService.getTokenByName(paramsMap.get("username")));
    }
}
